package com.stox.services.data.downloader.bse;

import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.zip.ZipInputStream;

import com.stox.services.data.downloader.model.AbstractExchangeDataDownloader;
import com.stox.shared.core.model.Bar;
import com.stox.shared.core.model.Exchange;
import com.stox.shared.core.model.Scrip;
import com.stox.shared.core.model.enumeration.BarSpan;
import com.stox.shared.core.model.enumeration.ScripType;
import com.stox.shared.core.model.intf.Callback;
import com.stox.shared.core.util.StringUtil;

public class BseExchangeDataDownloader extends AbstractExchangeDataDownloader {

	private Long BSE_ID = 1L; 
	private String downloadUrlBseStart = "http://www.bseindia.com/bhavcopy/eq";
	private String downloadUrlBseEnd = "_csv.zip";
	private String downloadUrlBseDateFormat = "ddMMyy";
	
	@Override
	public void download(Exchange exchange, BarSpan barSpan, Date date,
			Callback<List<Bar>, Void> callback) {
		if(!BarSpan.DAILY.equals(barSpan)){
			throw new UnsupportedOperationException("BarSpan "+barSpan.name()+" is not supported");
		}
		
		List<Bar> result = new ArrayList<>(3000);
		String data = download(getUri(date));
		String[] tokens = data.split("\n");
		for(String token : tokens){
			Bar bar = parse(token);
			if(null != bar){
				bar.setDate(date);
				result.add(bar);
			}
		}
		callback.execute(result);
	}
	
	public String getUri(Date date) {
		DateFormat dateFormat = new SimpleDateFormat(downloadUrlBseDateFormat);
		String uri = downloadUrlBseStart + dateFormat.format(date) + downloadUrlBseEnd;
		return 	uri;
	}
	
	public String download(String uri) {
		String output = null;
		try{
			ZipInputStream inStream = new ZipInputStream(new URL(uri).openStream());
	        byte[] buffer = new byte[1024];
	        int nrBytesRead;
	        StringWriter w = new StringWriter();
	        if (inStream.getNextEntry() != null) {
	            while ((nrBytesRead = inStream.read(buffer)) > 0) {
	            	w.write(new String(buffer,0,nrBytesRead));
	            }
	        }
	        w.flush();
	        w.close();
	        inStream.close();
			output = w.toString();
		}catch(IOException ie){
			output = "";
		}
		return output;
	}
	
	public Bar parse(String str) {
		if(!StringUtil.hasText(str)){
			return null;
		}
		Bar bar = new Bar();
		StringTokenizer t = new StringTokenizer(str, ",", false);
		try {
			bar.setScripId(Long.parseLong(t.nextToken()));
			Scrip scrip = new Scrip(ScripType.EQUITY);
			bar.setScrip(scrip);
			scrip.setId(bar.getScripId());
			scrip.setExchangeId(BSE_ID);
			scrip.setName(t.nextToken()); //Name
			t.nextToken(); //Group
			if (!"Q".equals(t.nextToken()))  return null;  // TODO handle type
			bar.setOpen(Double.parseDouble(t.nextToken()));
			bar.setHigh(Double.parseDouble(t.nextToken()));
			bar.setLow(Double.parseDouble(t.nextToken()));
			bar.setClose(Double.parseDouble(t.nextToken()));
			t.nextToken();//bar.setLast(Double.parseDouble(t.nextToken()));
			t.nextToken();//bar.setPreviousClose(Double.parseDouble(t.nextToken()));
			t.nextToken();//bar.setTrades(Double.parseDouble(t.nextToken()));
			bar.setVolume(Double.parseDouble(t.nextToken()));
			t.nextToken();//bar.setTurnover(Double.parseDouble(t.nextToken()));
		} catch (NumberFormatException nfe) {
			bar = null;
		} catch (Exception e) {
			e.printStackTrace();
			bar = null;
		}
		return bar;
	}

}
